package com.tukez.tmdb
import com.tukez.tmdb.model.Genre
import query.OrderBy
import query.Order
import query.Paging
import query.RatingBetween
import query.GenresSelector
import query.ReleaseBetween
import com.tukez.tmdb.model.Movie
import com.tukez.tmdb.util.DisjointBoundedView._
import model.Images
import model.MovieVersion
import query.MPAARating
import model.Translation
import com.tukez.tmdb.model.Person
import com.tukez.tmdb.model.PersonVersion
import com.tukez.tmdb.query.Hash
import com.tukez.tmdb.query.Genres

trait ITMDb {
  def Media: ITMDbMedia
  def Movie: ITMDbMovie
  def Person: ITMDbPerson
  def Genres: ITMDbGenres
}

trait ITMDbMedia {
  /** see http://api.themoviedb.org/2.1/methods/Media.getInfo
   */
  def getInfo(dvdId: String): Option[Movie]

  /** see http://api.themoviedb.org/2.1/methods/Media.getInfo
   */
  def getInfo(hash: Hash): Option[Movie]
}

trait ITMDbMovie {
  
  type GenresType = Int or Long or String or com.tukez.tmdb.query.Genres.Genre or Genre or GenresSelector[_]
  type CertsType = String or MPAARating.MPAARating
  
  /** see http://api.themoviedb.org/2.1/methods/Movie.browse
   *
   *  @param genres accepts Int, Long, String, Genres enum value or Genre.
   *  If you want to define multiple genres, you can pass either GenresAnd or GenresOr.
   *  Which type of value you use is a matter of preference, although you can't mix different types.
   *
   *  @param certifications accepts either List[String] or List[MPAARating]
   */
  def browse[A <% GenresType, B <% CertsType](
    orderBy: OrderBy.OrderBy,
    order: Order.Order,
    paging: Paging = null,
    query: String = "",
    minVotes: Int = -1,
    rating: RatingBetween = null,
    genres: A = null,
    release: ReleaseBetween = null,
    year: Int = -1,
    certifications: List[B] = Nil,
    companies: List[String] = Nil,
    countries: List[String] = Nil): List[Movie]

  /** see http://api.themoviedb.org/2.1/methods/Movie.getImages
   *
   *  `tmdbIdOrImdbId` type is either Int, Long or String
   */
  def getImages[A <% Int or Long or String](tmdbIdOrImdbId: A): Images

  /** see http://api.themoviedb.org/2.1/methods/Movie.getInfo
   */
  def getInfo(tmdbId: Long): Option[Movie]

  /** see http://api.themoviedb.org/2.1/methods/Movie.getLatest
   */
  def getLatest: MovieVersion

  /** see http://api.themoviedb.org/2.1/methods/Movie.getTranslations
   *
   *  `tmdbIdOrImdbId` type is either Int, Long or String
   */
  def getTranslations[A <% Int or Long or String](tmdbIdOrImdbId: A): List[Translation]

  /** see http://api.themoviedb.org/2.1/methods/Movie.getVersion
   *
   *  `tmdbIdOrImdbId` type is either Int, Long or String
   */
  def getVersion[A <% Int or Long or String](tmdbIdsOrImdbIds: A*): List[MovieVersion]

  /** see http://api.themoviedb.org/2.1/methods/Movie.imdbLookup
   */
  def imdbLookup(imdbId: String): Option[Movie]

  /** see http://api.themoviedb.org/2.1/methods/Movie.search
   */
  def search(title: String, year: Int = -1): List[Movie]
}

trait ITMDbPerson {
  /** see http://api.themoviedb.org/2.1/methods/Person.getInfo
   */
  def getInfo(tmdbId: Long): Option[Person]

  /** see http://api.themoviedb.org/2.1/methods/Person.getLatest
   */
  def getLatest: PersonVersion

  /** see http://api.themoviedb.org/2.1/methods/Person.getVersion
   */
  def getVersion(tmdbIds: Long*): List[PersonVersion]

  /** see http://api.themoviedb.org/2.1/methods/Person.search
   */
  def search(title: String): List[Person]
}

trait ITMDbGenres {
  /** see http://api.themoviedb.org/2.1/methods/Genres.getList
   */
  def getList: List[Genre]
}